import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import '../index.dart';

class RefreshTokenInstance {
  // 单例公开访问点
  factory RefreshTokenInstance() => _sharedInstance();

  // 静态私有成员，没有初始化
  static RefreshTokenInstance? _instance;

  // 私有构造函数
  RefreshTokenInstance._() {
    // 具体初始化代码
  }

  // 静态、同步、私有访问点
  static RefreshTokenInstance _sharedInstance() {
    return _instance ??= RefreshTokenInstance._();
  }

  bool isRefreshToken = false;
  bool isRefreshTokenSuccess = true;
}

class RefreshTokenInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    String? token = Global.profile.token;
    if (token != null) {
      options.headers[HttpGo.authorizationKey] = token;
    } else {
      options.headers.remove(HttpGo.authorizationKey);
    }

    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) async {
    // token过期
    if (err.response != null && err.response!.statusCode == 401) {
      Debug.info("token过期，重新刷新！");
      //如果已经有了其他刷新请求则等待
      if (RefreshTokenInstance().isRefreshToken) {
        _waitRefreshToken(err, handler);
        return;
      } else {
        String? token = await getToken(err, handler);
        if (token == null) {
          Debug.info("当前接口刷新token失败！");
          handler.next(err);
          // super.onError(err, handler);
          return;
        }
      }

      reRequest(err, handler);
    } else {
      super.onError(err, handler);
    }
  }

  Future<String?> getToken(
      DioError err, ErrorInterceptorHandler handler) async {
    try {
      //正在刷新token
      RefreshTokenInstance().isRefreshToken = true;
      RefreshTokenInstance().isRefreshTokenSuccess = false;
      Response response = await HttpGo.reserveDio.post("/gxsaas-auth/token",
          data: {
            "refreshToken": Global.profile.user!.refreshToken,
            "grantType": "refresh_token"
          },
          options: Options(headers: {
            HttpHeaders.contentTypeHeader: HttpGo.kContentTypeHeaderForm,
            HttpHeaders.authorizationHeader: 'Basic ' +
                base64.encode(
                    utf8.encode('${HttpGo.clientId}:${HttpGo.clientSecret}'))
          }, extra: {
            "noCache": true,
            "context": err.requestOptions.extra["context"] //本接口禁用缓存
          }));
      if (response.statusCode == 200) {
        ResponseData<User> responseData = ResponseData.fromJson(response.data,
            dataParseCallback: (data) => User.fromJson(data));

        if (responseData.success) {
          //清空所有缓存
          Global.netCache.cache.clear();
          //更新profile中的token信息
          Global.profile.token =
              'bearer ' + (responseData.dataModel?.accessToken ?? "");
          Global.profile.user = responseData.dataModel;
          Global.saveProfile();
          RefreshTokenInstance().isRefreshTokenSuccess = true;
          return Global.profile.token;
        }
      }
      return null;
    } on DioError catch (e) {
      Debug.info("--------dioError------");
      Debug.info(e.message);
      //退出登录 跳转到登录页
      Global.netCache.cache.clear();
      DataCache.clearData();
      //更新profile中的token信息
      Global.profile.token = null;
      Global.profile.user = null;
      Global.saveProfile();
      BuildContext? context = e.requestOptions.extra["context"];
      if (context != null) {
        //刷新token失败
        showToast("登录授权已失效，请重新登录！");
        Navigator.pushReplacementNamed(context, "login");
      }
    } on Error catch (e) {
      Debug.info("--------Error------");
      Debug.info(e.toString());
    } finally {
      RefreshTokenInstance().isRefreshToken = false;
    }
    return null;
  }

  Future<String?> reRequest(
      DioError err, ErrorInterceptorHandler handler) async {
    Debug.info("刷新成功，再次请求！");
    //更新profile中的token信息
    RequestOptions? request = err.response?.requestOptions;
    request!.headers[HttpGo.authorizationKey] = Global.profile.token;
    try {
      if (request.data is FormData) {
        FormData formData = FormData();
        formData.fields.addAll(request.data.fields);

        for (MapEntry mapFile in request.data.files) {
          formData.files.add(MapEntry(
              mapFile.key,
              MultipartFileExtended.fromFileSync(mapFile.value.filePath,
                  filename: mapFile.value.filename)));
        }
        request.data = formData;
      }
      //重新发起请求
      Response response = await HttpGo.reserveDio.request(request.path,
          data: request.data,
          options: Options(method: request.method, headers: request.headers),
          queryParameters: request.queryParameters,
          cancelToken: request.cancelToken,
          onReceiveProgress: request.onReceiveProgress);
      handler.resolve(response);
    } on DioError catch (e) {
      Debug.info("请求再次失败");
      handler.next(e);
    }
  }

  Future _waitRefreshToken(
      DioError err, ErrorInterceptorHandler handler) async {
    Future.delayed(const Duration(milliseconds: 500), () {
      if (RefreshTokenInstance().isRefreshToken) {
        _waitRefreshToken(err, handler);
      } else {
        if (!RefreshTokenInstance().isRefreshTokenSuccess) {
          Debug.info("其他接口刷新token失败！");
          handler.next(err);
        } else {
          reRequest(err, handler);
        }
      }
    });
  }

// Future _waitRefreshToken() async {
//   while (RefreshTokenInstance().isRefreshToken) {
//     //睡眠1s
//     sleep(const Duration(seconds: 1));
//     Debug.info("检测token是否刷新");
//   }
//   return null;
// }
}
